1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "chre/common.h"
18 #include "inc/test_util.h"
19 #include "test_base.h"
20
21 #include <gtest/gtest.h>
22 #include <cstdint>
23
24 #include "chre/core/event_loop_manager.h"
25 #include "chre/core/settings.h"
26 #include "chre/platform/fatal_error.h"
27 #include "chre/platform/linux/pal_ble.h"
28 #include "chre/util/dynamic_vector.h"
29 #include "chre_api/chre/ble.h"
30 #include "chre_api/chre/user_settings.h"
31 #include "test_util.h"
32
33 namespace chre {
34
35 namespace {
36
37 /**
38 * This test verifies that a nanoapp can query for BLE capabilities and filter
39 * capabilities. Note that a nanoapp does not require BLE permissions to use
40 * these APIs.
41 */
TEST_F(TestBase,BleCapabilitiesTest)42 TEST_F(TestBase, BleCapabilitiesTest) {
43 CREATE_CHRE_TEST_EVENT(GET_CAPABILITIES, 0);
44 CREATE_CHRE_TEST_EVENT(GET_FILTER_CAPABILITIES, 1);
45
46 struct App : public TestNanoapp {
47 uint32_t perms = NanoappPermissions::CHRE_PERMS_WIFI;
48
49 decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
50 const void *eventData) {
51 switch (eventType) {
52 case CHRE_EVENT_TEST_EVENT: {
53 auto event = static_cast<const TestEvent *>(eventData);
54 switch (event->type) {
55 case GET_CAPABILITIES: {
56 TestEventQueueSingleton::get()->pushEvent(
57 GET_CAPABILITIES, chreBleGetCapabilities());
58 break;
59 }
60
61 case GET_FILTER_CAPABILITIES: {
62 TestEventQueueSingleton::get()->pushEvent(
63 GET_FILTER_CAPABILITIES, chreBleGetFilterCapabilities());
64 break;
65 }
66 }
67 }
68 }
69 };
70 };
71
72 auto app = loadNanoapp<App>();
73
74 uint32_t capabilities;
75 sendEventToNanoapp(app, GET_CAPABILITIES);
76 waitForEvent(GET_CAPABILITIES, &capabilities);
77 ASSERT_EQ(capabilities, CHRE_BLE_CAPABILITIES_SCAN |
78 CHRE_BLE_CAPABILITIES_SCAN_RESULT_BATCHING |
79 CHRE_BLE_CAPABILITIES_SCAN_FILTER_BEST_EFFORT);
80
81 sendEventToNanoapp(app, GET_FILTER_CAPABILITIES);
82 waitForEvent(GET_FILTER_CAPABILITIES, &capabilities);
83 ASSERT_EQ(capabilities, CHRE_BLE_FILTER_CAPABILITIES_RSSI |
84 CHRE_BLE_FILTER_CAPABILITIES_SERVICE_DATA);
85 }
86
87 struct BleTestNanoapp : public TestNanoapp {
88 uint32_t perms = NanoappPermissions::CHRE_PERMS_BLE;
89
__anon4ce931120302chre::__anon4ce931120111::BleTestNanoapp90 decltype(nanoappStart) *start = []() {
91 chreUserSettingConfigureEvents(CHRE_USER_SETTING_BLE_AVAILABLE,
92 true /* enable */);
93 return true;
94 };
95
__anon4ce931120402chre::__anon4ce931120111::BleTestNanoapp96 decltype(nanoappEnd) *end = []() {
97 chreUserSettingConfigureEvents(CHRE_USER_SETTING_BLE_AVAILABLE,
98 false /* enable */);
99 };
100 };
101
102 /**
103 * This test validates the case in which a nanoapp starts a scan, receives
104 * at least one advertisement event, and stops a scan.
105 */
TEST_F(TestBase,BleSimpleScanTest)106 TEST_F(TestBase, BleSimpleScanTest) {
107 CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
108 CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
109 CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
110 CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
111
112 struct App : public BleTestNanoapp {
113 decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
114 const void *eventData) {
115 switch (eventType) {
116 case CHRE_EVENT_BLE_ASYNC_RESULT: {
117 auto *event = static_cast<const struct chreAsyncResult *>(eventData);
118 if (event->errorCode == CHRE_ERROR_NONE) {
119 uint16_t type =
120 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
121 ? SCAN_STARTED
122 : SCAN_STOPPED;
123 TestEventQueueSingleton::get()->pushEvent(type);
124 }
125 break;
126 }
127
128 case CHRE_EVENT_BLE_ADVERTISEMENT: {
129 TestEventQueueSingleton::get()->pushEvent(
130 CHRE_EVENT_BLE_ADVERTISEMENT);
131 break;
132 }
133
134 case CHRE_EVENT_TEST_EVENT: {
135 auto event = static_cast<const TestEvent *>(eventData);
136 switch (event->type) {
137 case START_SCAN: {
138 const bool success = chreBleStartScanAsync(
139 CHRE_BLE_SCAN_MODE_BACKGROUND, 0, nullptr);
140 TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
141 break;
142 }
143
144 case STOP_SCAN: {
145 const bool success = chreBleStopScanAsync();
146 TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
147 break;
148 }
149 }
150 break;
151 }
152 }
153 };
154 };
155
156 auto app = loadNanoapp<App>();
157
158 bool success;
159 sendEventToNanoapp(app, START_SCAN);
160 waitForEvent(START_SCAN, &success);
161 EXPECT_TRUE(success);
162 waitForEvent(SCAN_STARTED);
163 ASSERT_TRUE(chrePalIsBleEnabled());
164 waitForEvent(CHRE_EVENT_BLE_ADVERTISEMENT);
165
166 sendEventToNanoapp(app, STOP_SCAN);
167 waitForEvent(STOP_SCAN, &success);
168 EXPECT_TRUE(success);
169 waitForEvent(SCAN_STOPPED);
170 ASSERT_FALSE(chrePalIsBleEnabled());
171 }
172
TEST_F(TestBase,BleStopScanOnUnload)173 TEST_F(TestBase, BleStopScanOnUnload) {
174 CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
175 CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
176
177 struct App : public BleTestNanoapp {
178 decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
179 const void *eventData) {
180 switch (eventType) {
181 case CHRE_EVENT_BLE_ASYNC_RESULT: {
182 auto *event = static_cast<const struct chreAsyncResult *>(eventData);
183 if (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN &&
184 event->errorCode == CHRE_ERROR_NONE) {
185 TestEventQueueSingleton::get()->pushEvent(SCAN_STARTED);
186 }
187 break;
188 }
189
190 case CHRE_EVENT_TEST_EVENT: {
191 auto event = static_cast<const TestEvent *>(eventData);
192 switch (event->type) {
193 case START_SCAN: {
194 const bool success = chreBleStartScanAsync(
195 CHRE_BLE_SCAN_MODE_BACKGROUND, 0, nullptr);
196 TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
197 break;
198 }
199 }
200 break;
201 }
202 }
203 };
204 };
205
206 auto app = loadNanoapp<App>();
207 bool success;
208
209 sendEventToNanoapp(app, START_SCAN);
210 waitForEvent(START_SCAN, &success);
211 EXPECT_TRUE(success);
212 waitForEvent(SCAN_STARTED);
213 ASSERT_TRUE(chrePalIsBleEnabled());
214
215 unloadNanoapp(app);
216 ASSERT_FALSE(chrePalIsBleEnabled());
217 }
218
219 /**
220 * This test validates that a nanoapp can start a scan twice and the platform
221 * will be enabled.
222 */
TEST_F(TestBase,BleStartTwiceScanTest)223 TEST_F(TestBase, BleStartTwiceScanTest) {
224 CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
225 CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
226 CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
227 CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
228
229 struct App : public BleTestNanoapp {
230 decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
231 const void *eventData) {
232 switch (eventType) {
233 case CHRE_EVENT_BLE_ASYNC_RESULT: {
234 auto *event = static_cast<const struct chreAsyncResult *>(eventData);
235 if (event->errorCode == CHRE_ERROR_NONE) {
236 uint16_t type =
237 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
238 ? SCAN_STARTED
239 : SCAN_STOPPED;
240 TestEventQueueSingleton::get()->pushEvent(type);
241 }
242 break;
243 }
244
245 case CHRE_EVENT_BLE_ADVERTISEMENT: {
246 TestEventQueueSingleton::get()->pushEvent(
247 CHRE_EVENT_BLE_ADVERTISEMENT);
248 break;
249 }
250
251 case CHRE_EVENT_TEST_EVENT: {
252 auto event = static_cast<const TestEvent *>(eventData);
253 switch (event->type) {
254 case START_SCAN: {
255 const bool success = chreBleStartScanAsync(
256 CHRE_BLE_SCAN_MODE_BACKGROUND, 0, nullptr);
257 TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
258 break;
259 }
260
261 case STOP_SCAN: {
262 const bool success = chreBleStopScanAsync();
263 TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
264 break;
265 }
266 }
267 }
268 }
269 };
270 };
271
272 auto app = loadNanoapp<App>();
273 bool success;
274
275 sendEventToNanoapp(app, START_SCAN);
276 waitForEvent(START_SCAN, &success);
277 EXPECT_TRUE(success);
278 waitForEvent(SCAN_STARTED);
279
280 sendEventToNanoapp(app, START_SCAN);
281 waitForEvent(START_SCAN, &success);
282 EXPECT_TRUE(success);
283 waitForEvent(SCAN_STARTED);
284 waitForEvent(CHRE_EVENT_BLE_ADVERTISEMENT);
285
286 sendEventToNanoapp(app, STOP_SCAN);
287 waitForEvent(STOP_SCAN, &success);
288 EXPECT_TRUE(success);
289 waitForEvent(SCAN_STOPPED);
290 }
291
292 /**
293 * This test validates that a nanoapp can request to stop a scan twice without
294 * any ongoing scan existing. It asserts that the nanoapp did not receive any
295 * advertisment events because a scan was never started.
296 */
TEST_F(TestBase,BleStopTwiceScanTest)297 TEST_F(TestBase, BleStopTwiceScanTest) {
298 CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
299 CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
300 CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
301
302 struct App : public BleTestNanoapp {
303 decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
304 const void *eventData) {
305 switch (eventType) {
306 case CHRE_EVENT_BLE_ASYNC_RESULT: {
307 auto *event = static_cast<const struct chreAsyncResult *>(eventData);
308 if (event->errorCode == CHRE_ERROR_NONE) {
309 uint16_t type =
310 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
311 ? SCAN_STARTED
312 : SCAN_STOPPED;
313 TestEventQueueSingleton::get()->pushEvent(type);
314 }
315 break;
316 }
317
318 case CHRE_EVENT_BLE_ADVERTISEMENT: {
319 FATAL_ERROR("No advertisement expected");
320 break;
321 }
322
323 case CHRE_EVENT_TEST_EVENT: {
324 auto event = static_cast<const TestEvent *>(eventData);
325 switch (event->type) {
326 case STOP_SCAN: {
327 const bool success = chreBleStopScanAsync();
328 TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
329 break;
330 }
331 }
332 }
333 }
334 };
335 };
336
337 auto app = loadNanoapp<App>();
338 bool success;
339
340 sendEventToNanoapp(app, STOP_SCAN);
341 waitForEvent(STOP_SCAN, &success);
342 EXPECT_TRUE(success);
343 waitForEvent(SCAN_STOPPED);
344
345 sendEventToNanoapp(app, STOP_SCAN);
346 waitForEvent(STOP_SCAN, &success);
347 EXPECT_TRUE(success);
348
349 waitForEvent(SCAN_STOPPED);
350 unloadNanoapp(app);
351 }
352
353 /**
354 * This test verifies the following BLE settings behavior:
355 * 1) Nanoapp makes BLE scan request
356 * 2) Toggle BLE setting -> disabled
357 * 3) Toggle BLE setting -> enabled.
358 * 4) Verify things resume.
359 */
TEST_F(TestBase,BleSettingChangeTest)360 TEST_F(TestBase, BleSettingChangeTest) {
361 CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
362 CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
363 CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
364
365 struct App : public BleTestNanoapp {
366 decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
367 const void *eventData) {
368 switch (eventType) {
369 case CHRE_EVENT_BLE_ASYNC_RESULT: {
370 auto *event = static_cast<const struct chreAsyncResult *>(eventData);
371 if (event->errorCode == CHRE_ERROR_NONE) {
372 uint16_t type =
373 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
374 ? SCAN_STARTED
375 : SCAN_STOPPED;
376 TestEventQueueSingleton::get()->pushEvent(type);
377 }
378 break;
379 }
380
381 case CHRE_EVENT_BLE_ADVERTISEMENT: {
382 TestEventQueueSingleton::get()->pushEvent(
383 CHRE_EVENT_BLE_ADVERTISEMENT);
384 break;
385 }
386
387 case CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE: {
388 auto *event =
389 static_cast<const chreUserSettingChangedEvent *>(eventData);
390 bool enabled =
391 (event->settingState == CHRE_USER_SETTING_STATE_ENABLED);
392 TestEventQueueSingleton::get()->pushEvent(
393 CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, enabled);
394 break;
395 }
396
397 case CHRE_EVENT_TEST_EVENT: {
398 auto event = static_cast<const TestEvent *>(eventData);
399 switch (event->type) {
400 case START_SCAN: {
401 const bool success = chreBleStartScanAsync(
402 CHRE_BLE_SCAN_MODE_BACKGROUND, 0, nullptr);
403 TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
404 break;
405 }
406 }
407 }
408 }
409 };
410 };
411
412 auto app = loadNanoapp<App>();
413 bool success;
414
415 sendEventToNanoapp(app, START_SCAN);
416 waitForEvent(START_SCAN, &success);
417 EXPECT_TRUE(success);
418
419 waitForEvent(SCAN_STARTED);
420 waitForEvent(CHRE_EVENT_BLE_ADVERTISEMENT);
421
422 EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
423 Setting::BLE_AVAILABLE, false /* enabled */);
424 bool enabled;
425 waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
426 EXPECT_FALSE(enabled);
427 EXPECT_FALSE(
428 EventLoopManagerSingleton::get()->getSettingManager().getSettingEnabled(
429 Setting::BLE_AVAILABLE));
430 std::this_thread::sleep_for(std::chrono::milliseconds(100));
431 EXPECT_FALSE(chrePalIsBleEnabled());
432
433 EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
434 Setting::BLE_AVAILABLE, true /* enabled */);
435 waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
436 EXPECT_TRUE(enabled);
437 EXPECT_TRUE(
438 EventLoopManagerSingleton::get()->getSettingManager().getSettingEnabled(
439 Setting::BLE_AVAILABLE));
440 waitForEvent(CHRE_EVENT_BLE_ADVERTISEMENT);
441 EXPECT_TRUE(chrePalIsBleEnabled());
442 }
443
444 /**
445 * Test that a nanoapp receives a function disabled error if it attempts to
446 * start a scan when the BLE setting is disabled.
447 */
TEST_F(TestBase,BleSettingDisabledStartScanTest)448 TEST_F(TestBase, BleSettingDisabledStartScanTest) {
449 CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
450
451 struct App : public BleTestNanoapp {
452 decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
453 const void *eventData) {
454 switch (eventType) {
455 case CHRE_EVENT_BLE_ASYNC_RESULT: {
456 auto *event = static_cast<const struct chreAsyncResult *>(eventData);
457 if (event->errorCode == CHRE_ERROR_FUNCTION_DISABLED) {
458 TestEventQueueSingleton::get()->pushEvent(
459 CHRE_EVENT_BLE_ASYNC_RESULT);
460 }
461 break;
462 }
463
464 case CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE: {
465 auto *event =
466 static_cast<const chreUserSettingChangedEvent *>(eventData);
467 bool enabled =
468 (event->settingState == CHRE_USER_SETTING_STATE_ENABLED);
469 TestEventQueueSingleton::get()->pushEvent(
470 CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, enabled);
471 break;
472 }
473
474 case CHRE_EVENT_TEST_EVENT: {
475 auto event = static_cast<const TestEvent *>(eventData);
476 switch (event->type) {
477 case START_SCAN: {
478 const bool success = chreBleStartScanAsync(
479 CHRE_BLE_SCAN_MODE_BACKGROUND, 0, nullptr);
480 TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
481 break;
482 }
483 }
484 }
485 }
486 };
487 };
488
489 auto app = loadNanoapp<App>();
490
491 EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
492 Setting::BLE_AVAILABLE, false /* enable */);
493
494 bool enabled;
495 waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
496 EXPECT_FALSE(enabled);
497
498 bool success;
499 sendEventToNanoapp(app, START_SCAN);
500 waitForEvent(START_SCAN, &success);
501 EXPECT_TRUE(success);
502 waitForEvent(CHRE_EVENT_BLE_ASYNC_RESULT);
503 }
504
505 /**
506 * Test that a nanoapp receives a success response when it attempts to stop a
507 * BLE scan while the BLE setting is disabled.
508 */
TEST_F(TestBase,BleSettingDisabledStopScanTest)509 TEST_F(TestBase, BleSettingDisabledStopScanTest) {
510 CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
511 CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
512 CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
513
514 struct App : public BleTestNanoapp {
515 decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
516 const void *eventData) {
517 switch (eventType) {
518 case CHRE_EVENT_BLE_ASYNC_RESULT: {
519 auto *event = static_cast<const struct chreAsyncResult *>(eventData);
520 if (event->errorCode == CHRE_ERROR_NONE) {
521 uint16_t type =
522 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
523 ? SCAN_STARTED
524 : SCAN_STOPPED;
525 TestEventQueueSingleton::get()->pushEvent(type);
526 }
527 break;
528 }
529
530 case CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE: {
531 auto *event =
532 static_cast<const chreUserSettingChangedEvent *>(eventData);
533 bool enabled =
534 (event->settingState == CHRE_USER_SETTING_STATE_ENABLED);
535 TestEventQueueSingleton::get()->pushEvent(
536 CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, enabled);
537 break;
538 }
539
540 case CHRE_EVENT_TEST_EVENT: {
541 auto event = static_cast<const TestEvent *>(eventData);
542 switch (event->type) {
543 case STOP_SCAN: {
544 const bool success = chreBleStopScanAsync();
545 TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
546 break;
547 }
548 }
549 }
550 }
551 };
552 };
553
554 auto app = loadNanoapp<App>();
555
556 EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
557 Setting::BLE_AVAILABLE, false /* enable */);
558
559 bool enabled;
560 waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
561 EXPECT_FALSE(enabled);
562
563 bool success;
564 sendEventToNanoapp(app, STOP_SCAN);
565 waitForEvent(STOP_SCAN, &success);
566 EXPECT_TRUE(success);
567 waitForEvent(SCAN_STOPPED);
568 }
569
570 /**
571 * Test that a nanoapp can read RSSI successfully.
572 */
TEST_F(TestBase,BleReadRssi)573 TEST_F(TestBase, BleReadRssi) {
574 constexpr auto kConnectionHandle = 6;
575 constexpr auto kCookie = 123;
576
577 CREATE_CHRE_TEST_EVENT(RSSI_REQUEST, 1);
578 CREATE_CHRE_TEST_EVENT(RSSI_REQUEST_SENT, 2);
579
580 struct App : public BleTestNanoapp {
581 decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
582 const void *eventData) {
583 switch (eventType) {
584 case CHRE_EVENT_BLE_RSSI_READ: {
585 auto *event =
586 static_cast<const struct chreBleReadRssiEvent *>(eventData);
587 if (event->result.errorCode == CHRE_ERROR_NONE) {
588 TestEventQueueSingleton::get()->pushEvent(CHRE_EVENT_BLE_RSSI_READ);
589 }
590 break;
591 }
592 case CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE: {
593 auto *event =
594 static_cast<const chreUserSettingChangedEvent *>(eventData);
595 bool enabled =
596 (event->settingState == CHRE_USER_SETTING_STATE_ENABLED);
597 TestEventQueueSingleton::get()->pushEvent(
598 CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, enabled);
599 break;
600 }
601 case CHRE_EVENT_TEST_EVENT: {
602 auto event = static_cast<const TestEvent *>(eventData);
603 switch (event->type) {
604 case RSSI_REQUEST: {
605 const bool success =
606 chreBleReadRssiAsync(kConnectionHandle, (void *)kCookie);
607 TestEventQueueSingleton::get()->pushEvent(RSSI_REQUEST_SENT,
608 success);
609 break;
610 }
611 }
612 }
613 }
614 };
615 };
616
617 auto app = loadNanoapp<App>();
618
619 EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
620 Setting::BLE_AVAILABLE, true /* enabled */);
621 bool enabled;
622 waitForEvent(CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, &enabled);
623 EXPECT_TRUE(enabled);
624
625 bool success;
626 sendEventToNanoapp(app, RSSI_REQUEST);
627 waitForEvent(RSSI_REQUEST_SENT, &success);
628 EXPECT_TRUE(success);
629 waitForEvent(CHRE_EVENT_BLE_RSSI_READ);
630 }
631
632 /**
633 * This test validates that a nanoapp can start call start scan twice before
634 * receiving an async response. It should invalidate its original request by
635 * calling start scan a second time.
636 */
TEST_F(TestBase,BleStartScanTwiceBeforeAsyncResponseTest)637 TEST_F(TestBase, BleStartScanTwiceBeforeAsyncResponseTest) {
638 CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
639 CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
640 CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
641 CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
642
643 struct App : public BleTestNanoapp {
644 decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
645 const void *eventData) {
646 switch (eventType) {
647 case CHRE_EVENT_BLE_ASYNC_RESULT: {
648 auto *event = static_cast<const struct chreAsyncResult *>(eventData);
649 uint16_t type =
650 (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
651 ? SCAN_STARTED
652 : SCAN_STOPPED;
653 TestEventQueueSingleton::get()->pushEvent(type, event->errorCode);
654 break;
655 }
656 case CHRE_EVENT_TEST_EVENT: {
657 auto event = static_cast<const TestEvent *>(eventData);
658 switch (event->type) {
659 case START_SCAN: {
660 const bool success = chreBleStartScanAsync(
661 CHRE_BLE_SCAN_MODE_BACKGROUND, 0, nullptr);
662 TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
663 break;
664 }
665
666 case STOP_SCAN: {
667 const bool success = chreBleStopScanAsync();
668 TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
669 break;
670 }
671 }
672 }
673 }
674 };
675 };
676
677 auto app = loadNanoapp<App>();
678 bool success;
679
680 delayBleScanStart(true /* delay */);
681
682 sendEventToNanoapp(app, START_SCAN);
683 waitForEvent(START_SCAN, &success);
684 EXPECT_TRUE(success);
685
686 sendEventToNanoapp(app, START_SCAN);
687 waitForEvent(START_SCAN, &success);
688 EXPECT_TRUE(success);
689
690 uint8_t errorCode;
691 waitForEvent(SCAN_STARTED, &errorCode);
692 EXPECT_EQ(errorCode, CHRE_ERROR_OBSOLETE_REQUEST);
693
694 // Respond to the first scan request. CHRE will then attempt the next scan
695 // request at which point the PAL should no longer delay the response.
696 delayBleScanStart(false /* delay */);
697 EXPECT_TRUE(startBleScan());
698
699 waitForEvent(SCAN_STARTED, &errorCode);
700 EXPECT_EQ(errorCode, CHRE_ERROR_NONE);
701
702 sendEventToNanoapp(app, STOP_SCAN);
703 waitForEvent(STOP_SCAN, &success);
704 EXPECT_TRUE(success);
705 waitForEvent(SCAN_STOPPED);
706 }
707
708 } // namespace
709 } // namespace chre
710